//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package testcase_dao

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/db_ns"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_testcase_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type FolderInfoDbItem struct {
	FolderId       string            `bson:"_id"`
	ProjectId      string            `bson:"projectId"`
	Title          string            `bson:"title"`
	ParentFolderId string            `bson:"parentFolderId"`
	PermSetting    PermSettingDbItem `bson:"permSetting"`
	SubFolderCount uint32            `bson:"subFolderCount"`
	SubCaseCount   uint32            `bson:"subCaseCount"`
	CreateUserId   string            `bson:"createUserId"`
	CreateTime     int64             `bson:"createTime"`
	UpdateUserId   string            `bson:"updateUserId"`
	UpdateTime     int64             `bson:"updateTime"`
}

func (item *FolderInfoDbItem) ToFolderInfo() *project_testcase_api.FolderInfo {
	return &project_testcase_api.FolderInfo{
		FolderId:       item.FolderId,
		Title:          item.Title,
		ParentFolderId: item.ParentFolderId,
		PermSetting:    item.PermSetting.ToPermSetting(),
		SubFolderCount: item.SubFolderCount,
		SubCaseCount:   item.SubCaseCount,
		CreateUserId:   item.CreateUserId,
		CreateTime:     item.CreateTime,
		UpdateUserId:   item.UpdateUserId,
		UpdateTime:     item.UpdateTime,
		UserPerm:       &project_testcase_api.UserPerm{},
	}
}

type _FolderInfoDao struct {
	mc *mongo.Collection
}

func newFolderInfoDao(db *mongo.Database) (*_FolderInfoDao, error) {
	mc := db.Collection(db_ns.DB_NS_PROJECT_TEST_CASE + "folder")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"projectId", 1}, {"parentFolderId", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_FolderInfoDao{mc: mc}, nil
}

func (db *_FolderInfoDao) Insert(ctx context.Context, dbItem *FolderInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_FolderInfoDao) Exist(ctx context.Context, folderId, projectId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"_id": folderId, "projectId": projectId})
	return count > 0, err
}

func (db *_FolderInfoDao) Get(ctx context.Context, folderId, projectId string) (*FolderInfoDbItem, error) {
	retItem := &FolderInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"_id": folderId, "projectId": projectId}).Decode(retItem)
	return retItem, err
}

func (db *_FolderInfoDao) Remove(ctx context.Context, folderId, projectId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"_id": folderId, "projectId": projectId})
	return err
}

func (db *_FolderInfoDao) CountSubFolder(ctx context.Context, parentFolderId, projectId string) (uint32, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"projectId": projectId, "parentFolderId": parentFolderId})
	return uint32(count), err
}

func (db *_FolderInfoDao) ListSubFolder(ctx context.Context, parentFolderId, projectId string) ([]*FolderInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{"projectId": projectId, "parentFolderId": parentFolderId}, options.Find().SetSort(bson.M{"createTime": 1}))
	if err != nil {
		return nil, err
	}
	retList := []*FolderInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_FolderInfoDao) ListByProject(ctx context.Context, projectId string) ([]*FolderInfoDbItem, error) {
	cursor, err := db.mc.Find(ctx, bson.M{"projectId": projectId})
	if err != nil {
		return nil, err
	}
	retList := []*FolderInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_FolderInfoDao) UpdateSubFolderCount(ctx context.Context, folderId, projectId string, count uint32) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": folderId, "projectId": projectId}, bson.M{"$set": bson.M{"subFolderCount": count}})
	return err
}

func (db *_FolderInfoDao) UpdateSubCaseCount(ctx context.Context, folderId, projectId string, count uint32) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": folderId, "projectId": projectId}, bson.M{"$set": bson.M{"subCaseCount": count}})
	return err
}

func (db *_FolderInfoDao) UpdateTitle(ctx context.Context, folderId, projectId, title, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": folderId, "projectId": projectId}, bson.M{"$set": bson.M{"title": title, "updateUserId": updateUserId, "updateTime": updateTime}})
	return err
}

func (db *_FolderInfoDao) UpdatePermSetting(ctx context.Context, folderId, projectId string, permItem *PermSettingDbItem, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": folderId, "projectId": projectId}, bson.M{"$set": bson.M{"permSetting": permItem, "updateUserId": updateUserId, "updateTime": updateTime}})
	return err
}

func (db *_FolderInfoDao) UpdateParentFolder(ctx context.Context, folderId, projectId, parentFolderId, updateUserId string, updateTime int64) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"_id": folderId, "projectId": projectId}, bson.M{"$set": bson.M{"parentFolderId": parentFolderId, "updateUserId": updateUserId, "updateTime": updateTime}})
	return err
}
